<template>
  <div ref="el"></div>
</template>
<script setup lang="ts">
import { watch, ref, onMounted, onBeforeUnmount } from 'vue'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { codeforcesLanguage } from '../util/codeforces';
import { assign } from 'lodash-es';
type P = {
  original?: string,
  value?: string,
  theme?: string,
  language?: string,
  language2?: number,
  options?: monaco.editor.IStandaloneEditorConstructionOptions,
}

const n = ref(Symbol('editor'))


const props = withDefaults(defineProps<P>(), {
  value: '',
  original: '',
  theme: 'vs',
  language: 'cpp',
  language2: 54,
})

const editor = ref<() => monaco.editor.IStandaloneCodeEditor>(() => {
  // @ts-ignore
  return window[n.value]
})

type E = {
  (e: 'change', value?: string, event?: monaco.editor.IModelContentChangedEvent): void
  (e: 'editorWillMount', editor?: monaco.editor.IStandaloneCodeEditor): void
  (e: 'editorDidMount', monaco: monaco.editor.IStandaloneCodeEditor): void
}
const emit = defineEmits<E>()

const el = ref<HTMLDivElement>()

watch(() => props.options, (p) => {
  if (editor.value() && p) {
    editor.value().updateOptions(p);
  }
})

watch(() => props.value, (p) => {
  const editor1 = editor.value()
  if (editor1) {
    if (p !== editor1.getValue()) {
      editor1.setValue(p);
    }
  }
})

watch(() => props.theme, (newVal) => {
  if (editor.value() && newVal) {
    monaco.editor.setTheme(newVal);
  }
})

watch(() => props.language, (v) => {
  if (v === 'CPP' || v === 'C++' || v === 'C') {
    v = 'cpp'
  }
  const l = editor.value().getModel()
  if (l) {
    monaco.editor.setModelLanguage(l, v.toLowerCase());
  }
})

watch(() => props.language2, (n) => {
  const v = codeforcesLanguage.find(e => e.value === n)?.language as string
  const l = editor.value().getModel()
  if (l) {
    monaco.editor.setModelLanguage(l, v.toLowerCase());
  }
})

onBeforeUnmount(() => {
  editor.value().dispose()
})


onMounted(() => {
  initMonaco()


})


function initMonaco() {
  if (el.value) {
    emit('editorWillMount')
    const options = assign<monaco.editor.IStandaloneEditorConstructionOptions, monaco.editor.IStandaloneEditorConstructionOptions | undefined>({
      value: props.value,
      theme: props.theme,
      language: props.language,
      automaticLayout: true,
      mouseWheelZoom: true
    }, props.options)
    const editor = monaco.editor.create(el.value, options);
    const l = editor.getModel()
    if (l && props.language) {
      monaco.editor.setModelLanguage(l, props.language.toLowerCase());
    }
    editor.onDidChangeModelContent((event) => {
      const value = editor.getValue()
      if (props.value !== value) {
        emit("change", value, event);
      }
    });
    // @ts-ignore
    window[n.value] = editor;


    emit("editorDidMount", editor);
  }
}

defineExpose({
  editor,
  initMonaco
})


</script>
